"""
元数据提取器基类

定义视频元数据提取的通用接口和数据结构。
"""

from abc import abstractmethod
from typing import Dict, List, Any, Optional, Union
from dataclasses import dataclass, field
from datetime import datetime
import json

from src.core.plugin import ProcessorPlugin


@dataclass
class VideoMetadata:
    """视频元数据"""
    
    # 基本信息
    filename: str = ""
    filepath: str = ""
    file_size: int = 0  # 字节
    duration: float = 0.0  # 秒
    
    # 视频流信息
    width: int = 0
    height: int = 0
    fps: float = 0.0
    frame_count: int = 0
    video_codec: str = ""
    video_bitrate: int = 0  # bps
    pixel_format: str = ""
    aspect_ratio: str = ""
    
    # 音频流信息
    audio_codec: str = ""
    audio_bitrate: int = 0  # bps
    sample_rate: int = 0  # Hz
    channels: int = 0
    audio_duration: float = 0.0
    
    # 容器信息
    format_name: str = ""
    format_long_name: str = ""
    container_bitrate: int = 0
    
    # 时间信息
    creation_time: Optional[datetime] = None
    modification_time: Optional[datetime] = None
    
    # 元数据标签
    title: str = ""
    artist: str = ""
    album: str = ""
    genre: str = ""
    comment: str = ""
    copyright: str = ""
    
    # 技术信息
    color_space: str = ""
    color_range: str = ""
    color_primaries: str = ""
    transfer_characteristics: str = ""
    
    # 扩展信息
    chapters: List[Dict[str, Any]] = field(default_factory=list)
    streams: List[Dict[str, Any]] = field(default_factory=list)
    custom_metadata: Dict[str, Any] = field(default_factory=dict)
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        result = {}
        for key, value in self.__dict__.items():
            if isinstance(value, datetime):
                result[key] = value.isoformat() if value else None
            else:
                result[key] = value
        return result
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'VideoMetadata':
        """从字典创建"""
        # 处理datetime字段
        if 'creation_time' in data and data['creation_time']:
            if isinstance(data['creation_time'], str):
                data['creation_time'] = datetime.fromisoformat(data['creation_time'])
        
        if 'modification_time' in data and data['modification_time']:
            if isinstance(data['modification_time'], str):
                data['modification_time'] = datetime.fromisoformat(data['modification_time'])
        
        return cls(**data)
    
    def to_json(self) -> str:
        """转换为JSON字符串"""
        return json.dumps(self.to_dict(), indent=2, ensure_ascii=False, default=str)


@dataclass
class AudioMetadata:
    """音频元数据"""
    
    # 基本信息
    filename: str = ""
    filepath: str = ""
    file_size: int = 0
    duration: float = 0.0
    
    # 音频信息
    codec: str = ""
    bitrate: int = 0
    sample_rate: int = 0
    channels: int = 0
    bit_depth: int = 0
    
    # 格式信息
    format_name: str = ""
    format_long_name: str = ""
    
    # 元数据标签
    title: str = ""
    artist: str = ""
    album: str = ""
    genre: str = ""
    year: str = ""
    track: str = ""
    
    # 扩展信息
    custom_metadata: Dict[str, Any] = field(default_factory=dict)
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return self.__dict__.copy()
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'AudioMetadata':
        """从字典创建"""
        return cls(**data)


class MetadataExtractor(ProcessorPlugin):
    """
    元数据提取器抽象基类
    
    定义元数据提取的标准接口。
    """
    
    @property
    def name(self) -> str:
        return self.__class__.__name__
    
    @property
    def version(self) -> str:
        return "1.0.0"
    
    @property
    def description(self) -> str:
        return "元数据提取器基类"
    
    def get_supported_operations(self) -> List[str]:
        return ["extract_metadata", "extract_video_metadata", "extract_audio_metadata"]
    
    async def process(self, input_data: Any, operation: str = "extract_metadata", **kwargs) -> Any:
        """
        处理数据
        
        Args:
            input_data: 输入数据（通常是文件路径）
            operation: 操作类型
            **kwargs: 其他参数
        
        Returns:
            元数据
        """
        if operation == "extract_metadata":
            return await self.extract_metadata(input_data, **kwargs)
        elif operation == "extract_video_metadata":
            return await self.extract_video_metadata(input_data, **kwargs)
        elif operation == "extract_audio_metadata":
            return await self.extract_audio_metadata(input_data, **kwargs)
        else:
            raise ValueError(f"不支持的操作类型: {operation}")
    
    @abstractmethod
    async def extract_metadata(self, file_path: str, **kwargs) -> Union[VideoMetadata, AudioMetadata]:
        """
        提取文件元数据
        
        Args:
            file_path: 文件路径
            **kwargs: 其他参数
        
        Returns:
            元数据对象
        """
        pass
    
    @abstractmethod
    async def extract_video_metadata(self, video_path: str, **kwargs) -> VideoMetadata:
        """
        提取视频元数据
        
        Args:
            video_path: 视频文件路径
            **kwargs: 其他参数
        
        Returns:
            视频元数据
        """
        pass
    
    @abstractmethod
    async def extract_audio_metadata(self, audio_path: str, **kwargs) -> AudioMetadata:
        """
        提取音频元数据
        
        Args:
            audio_path: 音频文件路径
            **kwargs: 其他参数
        
        Returns:
            音频元数据
        """
        pass
    
    def get_supported_formats(self) -> List[str]:
        """获取支持的文件格式"""
        return ["mp4", "avi", "mov", "mkv", "mp3", "wav", "aac"]
    
    def is_supported_format(self, file_path: str) -> bool:
        """检查是否支持该文件格式"""
        from pathlib import Path
        ext = Path(file_path).suffix.lower().lstrip('.')
        return ext in self.get_supported_formats()
    
    def get_file_type(self, file_path: str) -> str:
        """获取文件类型"""
        from pathlib import Path
        ext = Path(file_path).suffix.lower().lstrip('.')
        
        video_formats = ["mp4", "avi", "mov", "mkv", "webm", "flv", "wmv", "m4v"]
        audio_formats = ["mp3", "wav", "aac", "flac", "ogg", "wma", "m4a"]
        
        if ext in video_formats:
            return "video"
        elif ext in audio_formats:
            return "audio"
        else:
            return "unknown"


class ExtractorFactory:
    """提取器工厂类"""
    
    _extractors: Dict[str, type] = {}
    
    @classmethod
    def register(cls, name: str, extractor_class: type) -> None:
        """注册提取器"""
        cls._extractors[name] = extractor_class
    
    @classmethod
    def create(cls, name: str, **kwargs) -> MetadataExtractor:
        """创建提取器实例"""
        if name not in cls._extractors:
            raise ValueError(f"未知的提取器类型: {name}")
        
        extractor_class = cls._extractors[name]
        return extractor_class(**kwargs)
    
    @classmethod
    def list_extractors(cls) -> List[str]:
        """列出所有注册的提取器"""
        return list(cls._extractors.keys())
    
    @classmethod
    def get_best_extractor(cls, file_path: str) -> str:
        """根据文件类型获取最佳提取器"""
        from pathlib import Path
        ext = Path(file_path).suffix.lower().lstrip('.')
        
        # 根据文件扩展名选择最佳提取器
        if ext in ["mp4", "avi", "mov", "mkv", "webm"]:
            return "composite"  # 视频文件使用复合提取器
        elif ext in ["mp3", "wav", "aac", "flac"]:
            return "ffmpeg"     # 音频文件使用FFmpeg
        else:
            return "composite"  # 默认使用复合提取器


# 提取器装饰器
def extractor(name: str):
    """提取器注册装饰器"""
    def decorator(cls):
        ExtractorFactory.register(name, cls)
        return cls
    return decorator
